import { Scene } from '@babylonjs/core/scene';
import { CreateUISelectGrid, IUISelectGridOptions, UISelectGrid } from '../control/ui-select-grid';
import { Mesh } from '@babylonjs/core/Meshes/mesh';
import { CreateHandleTo, IHandle, RemoveHandle } from '../../data/data-handle';
import { AbstractScrollList, IAbstractScrollListOptions } from './abstract-scroll-list';

/**
 * 滚动条容器选择组件参数对象
 * @param enableMultiSelect 启用多选
 * @param irrevocable 不可撤销选择
 */
interface IUIScrollGridListOptions extends IAbstractScrollListOptions {
    enableMultiSelect?: boolean,
    irrevocable?: boolean,
}

/**
 * 滚动条容器选择组件
 * @param name 名称
 * @param scene 所在场景
 * @param options 参数对象
 */
class UIScrollGridList extends AbstractScrollList<UISelectGrid, IUISelectGridOptions> {

    private _selectHandles: IHandle<string[]>[] = [];

    /**
     * 被选择的名称
     */
    public readonly selected: string[] = [];

    constructor(name: string, scene: Scene, options?: IUIScrollGridListOptions) {
        super(name, scene, options);
        this.updateBlockSize();
    }

    /**
     * 选择
     * @param names 名称集合
     */
    public select(...names: string[]): void {
        const sig = !(this.options as IUIScrollGridListOptions).enableMultiSelect;
        let change = false;
        for (const n of names) {
            if (this.selected.includes(n)) continue;
            if (sig) {
                this.selected.length = 0;
                this.members.forEach(m => {
                    m.avoidEventHandle = true;
                    m.isSelected = false;
                    m.avoidEventHandle = false;
                });
            }
            this.selected.push(n);
            change = true;
            for (const mb of this.members) {
                if (mb.name === n) {
                    mb.avoidEventHandle = true;
                    mb.isSelected = true;
                    mb.avoidEventHandle = false;
                    break;
                }
            }
            if (sig) break;
        }
        if (change) this._selectHandles.forEach(h => h.callback(this.selected));
    }

    /**
     * 取消选择
     * @param names 名称集合
     */
    public unselect(...names: string[]): void {
        const irv = (this.options as IUIScrollGridListOptions).irrevocable;
        let change = false;
        for (const n of names) {
            let idx = this.selected.indexOf(n);
            if (idx < 0) continue;
            if (this.selected.length === 1 && irv) {
                for (const mb of this.members) {
                    if (mb.name === n) {
                        mb.avoidEventHandle = true;
                        mb.isSelected = true;
                        mb.avoidEventHandle = false;
                        break;
                    }
                }
                break;
            }
            for (const mb of this.members) {
                if (mb.name === n) {
                    mb.avoidEventHandle = true;
                    mb.isSelected = false;
                    mb.avoidEventHandle = false;
                    break;
                }
            }
            this.selected.splice(idx, 1);
            change = true;
        }
        if (change) this._selectHandles.forEach(h => h.callback(this.selected));
    }

    /**
     * 清除选择 
     */
    public clearSelect(): void {
        const irv = (this.options as IUIScrollGridListOptions).irrevocable;
        if (this.selected.length <= (irv ? 1 : 0)) return;
        for (let i = irv ? 1 : 0; i < this.selected.length; i++) {
            const n = this.selected[i];
            for (const mb of this.members) {
                if (mb.name === n) {
                    mb.avoidEventHandle = true;
                    mb.isSelected = false;
                    mb.avoidEventHandle = false;
                    break;
                }
            }
            this.selected.splice(i, 1);
            i--;
        }
        this._selectHandles.forEach(h => h.callback(this.selected));
    }

    /**
     * 添加选择变化时的回调函数对象
     * @param func 回调函数
     * @returns 回调函数对象
     */
    public onSelect(func: { (names: string[]): void }): IHandle<string[]> {
        return CreateHandleTo<string[]>(func, this._selectHandles);
    }

    /**
     * 移除回调函数对象
     * @param handle 回调函数对象或其id
     */
    public removeSelectHandle(handle: number | IHandle<string[]>): void {
        RemoveHandle(handle, this._selectHandles);
    }

    protected generateMember(name: string, options?: IUISelectGridOptions | undefined): UISelectGrid {
        const ops = options || {};
        ops.cornerRadius = ops.cornerRadius || 5;
        ops.text = ops.text || name;
        ops.background = ops.background || '#000000';
        ops.enabledStyle = (enabled, scope) => {
            const scp = scope as UISelectGrid;
            scp.control.disabledColor = ops.background || '#000000';
            if (enabled) {
                (scp.container as Mesh).visibility = 1;
            } else {
                (scp.container as Mesh).visibility = 0.2;
            }
        };

        return CreateUISelectGrid(name, this.scene, options!, (isChecked: boolean) => {
            isChecked ? this.select(name) : this.unselect(name);
        });
    }

}

/**
 * 创建滚动条容器选择组件
 * @param name 名称
 * @param scene 所在场景
 * @param options 参数对象
 * @param items 成员的名称及参数对象
 * @param callback 回调函数
 * @returns 创建的组件
 */
const CreateUIScrollGridList = (name: string, scene: Scene, options: IUIScrollGridListOptions, items: Array<{ name: string, option?: IUISelectGridOptions }>, callback?: { (selected: string[]): void }): UIScrollGridList => {
    const sg = new UIScrollGridList(name, scene, options);
    for (const item of items) {
        sg.add(item.name, item.option);
    }
    if (callback) sg.onSelect(callback);
    return sg;
};


export { UIScrollGridList, CreateUIScrollGridList };
export type { IUIScrollGridListOptions };